Remediation scripts/Disk encryption should be applied on virtual machines/Powershell/Enable-AzureVMDiskEncryption.ps1 (102 lines of code) (raw):

Write-Verbose "Checking for Azure module..." $AzModule = Get-Module -Name "Az.*" -ListAvailable if ($AzModule -eq $null) { Write-Verbose "Azure PowerShell module not found" # Check for Admin Privleges $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) $isadmin = ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) if($isadmin -eq $False) { # No Admin, install to current user Write-Warning -Message "Can not install Az Module. You are not running as Administrator" Write-Warning -Message "Installing Az Module to Current User Scope" Install-Module Az -Scope CurrentUser -Force Install-Module Az.Security -Scope CurrentUser -Force } Else { # Admin, install to all users Install-Module Az -Force Install-Module Az.Security -Force } else { if ($AzModule.Name -notcontains "Az.Security") { Write-Verbose "Azure Security PowerShell module not found" if($isadmin -eq $False){ Write-Warning -Message "Can not install Az Security Module. You are not running as Administrator" Write-Warning -Message "Installing Az Security Module to Current User Scope" Install-Module Az.Security -Scope CurrentUser -Force } Else { # Admin, install to all users Install-Module Az.Security -Force } } } } # Check/Set Execution Policy if ((Get-ExecutionPolicy).value__ -eq '3') { Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Force } # Import Modules Import-Module Az Import-Module Az.Security # Login to Azure Login-AzAccount # Get All Subs $Subscriptions = Get-AzSubscription # Loop Through Subs foreach($Subscription in $Subscriptions) { $Id = ($Subscription.Id) Select-AzSubscription $Id # Get Security Task for Storage Security $SecurityTasks += Get-AzSecurityTask | Where-Object {$_.RecommendationType -eq "EncryptionOnVm"} } foreach($SecurityTask in $SecurityTasks) { $sub = $securityTask.Id.Split("/")[2] $vm = $securityTask.ResourceId.Split("/")[8] $vmlocation = (Get-AzVm -Name $vm).Location $vmrg = (Get-AzVm -Name $vm).ResourceGroupName Select-AzSubscription $sub # Check for Existing Keyvault [array]$vaultnames = $null [array]$localvault = $null $vaultnames += (Get-AzKeyVault).VaultName foreach ($vaultname in $vaultnames) { $vaultdetails = Get-AzKeyVault -VaultName $vaultname # Find local KVs with Disk Encryption Flag if(($vaultdetails.EnabledForDiskEncryption -eq $true) -and ($vmlocation -eq $vaultdetails.Location)) { $localvault += $vaultdetails.VaultName } } # Use local KV if one exists if ($localvault -ne $null) { $localvaultdetails = Get-AzKeyVault -VaultName $localvault[0] # Encrypt VM using existing KV Set-AzVMDiskEncryptionExtension -ResourceGroupName $vmrg -VMName $vm -DiskEncryptionKeyVaultUrl $localvaultdetails.VaultUri -DiskEncryptionKeyVaultId $localvaultdetails.ResourceId -VolumeType All -SkipVmBackup -Force } # If no local KV exists, create one. else { # Create KV with unique name, allowing for long location names $subid = $sub.split("-")[0].substring(0,4) $vaultname = "${vmlocation}${subid}" $vaultRG = "DiskEncryptionRG-${vmlocation}" New-AzResourceGroup –Name $vaultRG –Location $vmlocation New-AzKeyVault -VaultName $vaultname -ResourceGroupName $vaultRG -Location $vmlocation -EnableSoftDelete -EnabledForDeployment -EnabledForTemplateDeployment -EnabledForDiskEncryption $kvid = (Get-AzKeyVault -VaultName $vaultname -ResourceGroupName $vaultRG).ResourceId $kvurl = (Get-AzKeyVault -VaultName $vaultname -ResourceGroupName $vaultRG).VaultUri # Encrypt VM Set-AzVMDiskEncryptionExtension -ResourceGroupName $vmrg -VMName $vm -DiskEncryptionKeyVaultUrl $kvurl -DiskEncryptionKeyVaultId $kvid -VolumeType All -SkipVmBackup -Force } }